package com.hyfrogx.modules.sys.oauth2;

import cn.hutool.core.util.ObjectUtil;
import com.hyfrogx.common.utils.ShiroUtils;
import com.hyfrogx.modules.sys.entity.SysUserEntity;
import com.hyfrogx.modules.sys.entity.SysUserTokenEntity;
import com.hyfrogx.modules.sys.service.ShiroService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * TODO 指定授权域
 *
 * @author crazypenguin
 * @version 1.0.0
 * @createdate 2019/1/2
 */
@Component
public class AuthRealm extends AuthorizingRealm {
	@Autowired
	private ShiroService shiroService;

	@Override
	public boolean supports(AuthenticationToken token) {
		return token instanceof MyToken || token instanceof UsernamePasswordToken;
	}

	/**
	 * 授权(验证权限时调用)
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SysUserEntity user = (SysUserEntity) principals.getPrimaryPrincipal();
		Long userId = user.getUserId();

		//用户权限列表
		Set<String> permsSet = shiroService.getUserPermissions(userId);

		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.setStringPermissions(permsSet);
		return info;
	}

	/**
	 * 认证(登录时调用)
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		SysUserEntity user = null;
		String accessToken = "" ;
		if (token instanceof MyToken) {
			accessToken = (String) token.getPrincipal();
			//根据accessToken，查询用户信息
			SysUserTokenEntity tokenEntity = shiroService.queryByToken(accessToken);
			//token失效
			if (tokenEntity == null || tokenEntity.getExpireTime().getTime() < System.currentTimeMillis()) {
				throw new IncorrectCredentialsException("token失效，请重新登录");
			}
			//查询用户信息
			user = shiroService.queryUser(tokenEntity.getUserId());
			if (ObjectUtil.isNull(user)) {
				throw new UnknownAccountException("用户无效");
			}
		} else if (token instanceof UsernamePasswordToken) {
			UsernamePasswordToken form = (UsernamePasswordToken) token;
			//查询用户信息
			user = shiroService.queryByUserName(form.getUsername());
			if (ObjectUtil.isNull(user)) {
				throw new UnknownAccountException();
			}
			//账号不存在、密码错误
			if (ObjectUtil.isNull(user) || !user.getPassword().equals(new Sha256Hash(form.getPassword(), user.getSalt()).toHex())) {
				throw new UnknownAccountException("账号或密码不正确");
			}

			accessToken = shiroService.createToken();
			ShiroUtils.setSessionAttribute("accessToken", accessToken);
			form.setPassword(accessToken.toCharArray());
		}

		//账号锁定
		if (user.getStatus() == 0) {
			throw new LockedAccountException("账号已被锁定,请联系管理员");
		}

		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, accessToken, getName());
		return info;
	}
}
